/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package PhysicCollection;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.AffineTransform;
import java.net.URL;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JPanel;

/**
 *
 * @author Mr.D
 */
public class BulletPanel extends JPanel implements MouseListener, MouseMotionListener, Runnable{

    
    private int delaytime = 0, delay = 0, px = 400;
    private double d1 = 10, d2 = 30, d3 = 20;
    private double angle1 = 0, angle2 = 0, angle3 = Math.PI, angle4 = Math.PI;
    private double angle5 = 0, angle6 = Math.PI*0.4, angle7 = Math.PI*0.8, angle8 = Math.PI*1.2, angle9 = Math.PI*1.6;
    private double angle10 = Math.PI/2, angle11 = Math.PI/2;
    private int x1 = 0, y1 = 0, x2 = 0, y2 = 0, x3 = 0, y3 = 0, x4 = 0, y4 = 0;
    private int x5 = 0, y5 = 0, x6 = 0, y6 = 0, x7 = 0, y7 = 0, x8 = 0, y8 = 0, x9 = 0, y9 = 0;

    private int circlesdelay = 5;


    private int targetx = 0, targety = 0;
    private int m_taichi_heard_x = 0, m_taichi_heard_y = 0;
    private Random random = new Random();
    private int la = 0, lb = 0, lc = 0;
    private int lx, ly;
    private URL rocketimgurl = this.getClass().getResource("/resources/rocket.gif");
    private Image im = this.getToolkit().getImage(rocketimgurl);
    private AffineTransform at = new AffineTransform();
    private Graphics2D g2d;
    private int hidetagetx = 0, hidetagety = 0;
    private int hidelinea = 0, hidelineb = 0, hidelinec = 0;
    private long starttime = 0;
    private boolean come = false;
    private int state = 0;
    private int rwc = 200, gwc = 200, bwc = 200;
    private int rbc = 200, gbc = 200, bbc = 200;
    private int rmc = 0, gmc = 0, bmc = 0;
    private Color blackcolor = new Color(rbc, gbc, bbc);
    private Color whitecolor = new Color(rwc, gwc, bwc);
    private double angle12 = Math.PI/2, angle13 = 3*Math.PI/2;
    private int x10 = -20, y10 = -20, x11= -20, y11 = -20;
    private int eyewidth = 40;
    private Color smallcircleblack = new Color(rmc,gmc,bmc);
    private Color smallcirclewhite = new Color(255 - rmc, 255 - gmc, 255 - bmc);
    
    private int bulletx = 400;
    private int bullety = 600;
    private int bulletxx = 0;
    private int bulletyy = 0;


    //use for auto gun
    private double directionAngle= 0;

    //bullet array
    private ArrayList<Bullet> bulletlist = new ArrayList<Bullet>();


    //homing missle
    private HomingMissile missile;
    private double missileangle2 = 0;
    private double missileangle3 = 0;


    //missilearray
    private ArrayList<HomingMissile> m_missiles_arraylist;

    //missile ues line
    private int missilelineparama;
    private int missilelineparamb;
    private int missilelineparamc;



    //number format
     private NumberFormat numberformat;

    //use for rocker image
    private int rocketimagex =5, rocketimagey = 550;
    private double rocketimageangle = 0;
    private double rocketimageanglewithgun = 0;

    //use for gravity simulation
    private int gravityballx = 0;
    private int gravitybally = 600;
    private double ballvelocity = 100;
    private double ballvelocityix;
    private double ballvelocityiy;
    private double ballvelocityx;
    private double ballvelocityy;
    private double balltime = 0;
    private int ballangle = 90;

    //for gunny shot
    private int gunnyangle;
    private double gunnypower;
    private int gunnyposx = 60;
    private int gunnyposy = 550;
    private boolean powerdirectiondown = false;
    private boolean shoted = false;
    private boolean outofscreen = true;
    private int gunnybulletx = 20;
    private int gunnybullety = 600;
    private double gunnyvelocityix;
    private double gunnyvelocityiy;
    private double gunnybullettime = 0;
    private double gunnybulletshottime = 0;
    private double gunnyvelocityy=0;


    //for konsiddon shot
    private double kalsiddon_big_bullet_angle=0;
    private double timewhenreachtop=0;
    private boolean create_virtual_taget = true;
    private int max_kalsiddon_child_missile = 4;
    private double [] kalsiddon_virtual_target_angle;
    private Point[] kalsiddon_virtual_target;
    private HomingMissile[] kalsiddon_child_missile;
    private int kalsiddon_angle_pertarget;
    private int kalsiddon_bullet_reached_top_posx = 0;
    private int kalsiddon_bullet_reached_top_posy = 0;
    private boolean hit_virtual_target = false;


    //for eyes
    private int eyesposx;
    private int eyesposy;
    private int eyesirisx1;
    private int eyesirisy1;
    private int eyesirisx2;
    private int eyesirisy2;
    private double eyesangletorotate1;
    private int maxeyesirisdistance;
    private double eyesangletorotate2;

    private int traildelayupdatetime = 0;
    private static int S_MAX_5_TRAIL_LENGTH = 50;
    private short[] trailtail1posx;
    private short[] trailtail1posy;
    private short[] trailtail2posx;
    private short[] trailtail2posy;
    private short[] trailtail3posx;
    private short[] trailtail3posy;
    private short[] trailtail4posx;
    private short[] trailtail4posy;
    private short[] trailtail5posx;
    private short[] trailtail5posy;

    //add physic object for gunny shadown
    private PhysicObject[] physicobjectarray;
    private int pressed_count = 0;
    private int maxphysicobject = 5;
    private int currentobject = 0;
    private int timebetweentwoobject = 50;//time between 2 object is 50 miliseconds

    //add bullet type    
    private static final int BULLET_TYPE_GUNNY = 0;
    private static final int BULLET_TYPE_RANDOM = 1;
    private static final int BULLET_TYPE_KALSIDDON = 2;
    private static final int BULLET_TYPE_MAGE = 3;
    private static final int BULLET_TYPE_OTHER2 = 4;
    private static int BULLET_TYPE = BULLET_TYPE_MAGE;

    //for debug mouse position
    private int m_current_mouse_x = -1;
    private int m_current_mouse_y = -1;

    //for rotate polygon
    private Rectangle rotate_rect;
    private Polygon rotate_triangle;
    private int[] polygon_x, polygon_y;
    private int polygon_point_number = 3;

    //for mage effect
    private double mage_virtual_taget_angle, m_mage_current_angle;
    private static int S_MAGE_TRAIL_LENGTH = 50;
    private int mage_delay1_x[] = new int[S_MAGE_TRAIL_LENGTH];
    private int mage_delay1_y[] = new int[S_MAGE_TRAIL_LENGTH];
    private int mage_delay2_x[] = new int[S_MAGE_TRAIL_LENGTH];
    private int mage_delay2_y[] = new int[S_MAGE_TRAIL_LENGTH];
    private int mage_point1_x;
    private int mage_point1_y;
    private int mage_point2_x;
    private int mage_point2_y;
    private static final int S_MAGE_ADDITION_ANGLE = 4;
    private static final int S_MAGE_POINT_MAX_DISTANCE = 20;

    //game control
    private boolean m_is_game_pause;


    //for mc
    private int m_mc_pos_x, m_mc_pos_y;
    private double m_mc_current_angle;
    private int m_mc_delay_beetween_2_bullet;
    private static final int MC_MOVE_SPEED = 2;
    private static final int MC_RADIUS = 10;
    private boolean keyuppressed, keydownpressed, keyleftpressed, keyrightpressed;
    private boolean m_is_can_fire;
    private boolean m_is_mc_gun_shooting;
    private Polygon m_mc_triangle;
    private int[] m_mc_triangle_x_vertices, m_mc_triangle_y_vertices;
    private int m_mc_vertices_number = 3;
    private int[] m_mc_trail_point_x, m_mc_trail_point_y;
    private static final int S_MC_TRAIL_POINT_COUNT = 50;
    private static final int S_MC_MISSILE_WAVE_DELAY_TIME = 250;
    private static final int S_MC_MISSILE_SHOOT_DELAY_TIME = 1000;
    private int m_mc_current_missile_wave;
    private static final int S_MC_MISSILE_MAX_WAVE = 3;
    private boolean m_is_missile_shooting;
    private static final int S_MC_SHOOT_MISSILE_DISTANCE = 10;
    private int[] m_mc_max_missile_per_wave;
    private double m_mc_missiles_last_shoot_time;
    private boolean[] m_is_shoot_current_wave;


     //for 2 missile near mc
    private int m_mc_missile_1_posx = 0;
    private int m_mc_missile_1_posy = 0;
    private int m_mc_missile_2_posx = 0;
    private int m_mc_missile_2_posy = 0;
    private static final int S_MC_EQUIPPED_MISSILE_DISTANCE = 10;
    private static final int S_MC_BULLETS_SPEED = 10;
    

    public BulletPanel(){
        lx = 0;
        ly = 0;
        trailtail1posx = new short[S_MAX_5_TRAIL_LENGTH];
        trailtail1posy = new short[S_MAX_5_TRAIL_LENGTH];
        trailtail2posx = new short[S_MAX_5_TRAIL_LENGTH];
        trailtail2posy = new short[S_MAX_5_TRAIL_LENGTH];
        trailtail3posx = new short[S_MAX_5_TRAIL_LENGTH];
        trailtail3posy = new short[S_MAX_5_TRAIL_LENGTH];
        trailtail4posx = new short[S_MAX_5_TRAIL_LENGTH];
        trailtail4posy = new short[S_MAX_5_TRAIL_LENGTH];
        trailtail5posx = new short[S_MAX_5_TRAIL_LENGTH];
        trailtail5posy = new short[S_MAX_5_TRAIL_LENGTH];
        for(int i = 0; i < S_MAX_5_TRAIL_LENGTH; i ++){
            trailtail1posx[i] = -5;
            trailtail1posy[i] = -5;
            trailtail2posx[i] = -5;
            trailtail2posy[i] = -5;
            trailtail3posx[i] = -5;
            trailtail3posy[i] = -5;
            trailtail4posx[i] = -5;
            trailtail4posy[i] = -5;
            trailtail5posx[i] = -5;
            trailtail5posy[i] = -5;
        }    
//        mainthread = new Thread(this);
        //ini for ball
        ballvelocityix = (ballvelocity*Math.cos(Math.toRadians(ballangle)));
        ballvelocityiy = (ballvelocity*Math.sin(Math.toRadians(ballangle)));
        //ini for gunny bullet             
        starttime = System.currentTimeMillis();
        eyesposx = 400;
        eyesposy = 200;
        eyesirisx1 = eyesposx;
        eyesirisy1 = eyesposy;
        eyesangletorotate1 = 0;
        eyesirisx2 = eyesirisx1;
        eyesirisy2 = eyesirisy1;
        eyesangletorotate2 = 0;
        maxeyesirisdistance = 25;
        missile = new HomingMissile(0, getHeight(), 0, 0, 0);
        m_missiles_arraylist = new ArrayList<HomingMissile>();
        numberformat = NumberFormat.getInstance();        
        kalsiddon_child_missile = new HomingMissile[max_kalsiddon_child_missile];
        kalsiddon_virtual_target_angle = new double[max_kalsiddon_child_missile];
        kalsiddon_virtual_target = new Point[max_kalsiddon_child_missile];
        for(int i = 0; i < max_kalsiddon_child_missile; i ++){
            kalsiddon_virtual_target[i] = new Point();
        }
        kalsiddon_angle_pertarget = 120/max_kalsiddon_child_missile;

        //for rotate object
        rotate_rect = new Rectangle(-50, -50, 100, 100);
        polygon_x = new int[polygon_point_number];
        polygon_y = new int[polygon_point_number];
        polygon_x[0] = 0;
        polygon_x[1] = -50;
        polygon_x[2] = 50;
        polygon_y[0] = -50;
        polygon_y[1] = 50;
        polygon_y[2] = 50;
        rotate_triangle = new Polygon(polygon_x, polygon_y, polygon_point_number);

        //call culate gunny angle before draw

        gunnyangle = 80;
        gunnypower = 80;
        gunnyposx = (int)(20 + 40* Math.cos(Math.toRadians(gunnyangle)));
        gunnyposy = (int)(550 - 40* Math.sin(Math.toRadians(gunnyangle)));
        mage_point1_x = mage_point2_x = gunnyposx;
        mage_point1_y = mage_point2_y = gunnyposy;


        //for mage shoot
        mage_virtual_taget_angle = 0;
        m_mage_current_angle = 0;

        //ini game control
        m_is_game_pause = false;

        //ini mc
        m_mc_pos_x = 400;
        m_mc_pos_y = 400;
        m_is_can_fire = false;
        m_mc_current_angle = 0;
        m_mc_delay_beetween_2_bullet = 3;
        keyuppressed = keydownpressed = keyleftpressed = keyrightpressed = false;
        m_is_mc_gun_shooting = false;
        m_mc_triangle_x_vertices = new int[m_mc_vertices_number];
        m_mc_triangle_y_vertices = new int[m_mc_vertices_number];
        m_mc_triangle_x_vertices[0] = 0;
        m_mc_triangle_x_vertices[1] = -10;
        m_mc_triangle_x_vertices[2] = 10;
        m_mc_triangle_y_vertices[0] = -15;
        m_mc_triangle_y_vertices[1] = 5;
        m_mc_triangle_y_vertices[2] = 5;
        m_mc_triangle = new Polygon(m_mc_triangle_x_vertices, m_mc_triangle_y_vertices, m_mc_vertices_number);
        m_mc_trail_point_x = new int[S_MC_TRAIL_POINT_COUNT];
        m_mc_trail_point_y = new int[S_MC_TRAIL_POINT_COUNT];
        for(int i = 0; i < S_MC_TRAIL_POINT_COUNT; i ++){
            m_mc_trail_point_x[i] = 0;
            m_mc_trail_point_y[i] = 0;
        }
        Reset_MC_Missiles_State();
    }
    
    @Override
    public void paint(Graphics g){

        g.setColor(new Color(200, 200, 200));
        g.fillRect(0, 0, this.getWidth(), this.getHeight());


        //test reflect
//        g.setColor(Color.BLACK);
//        g.drawLine(m_current_mouse_x, m_current_mouse_y, getWidth()/2, getHeight()/2);
//        int normal_vector_x = 3;
//        int normal_vector_y = 2;
//        int normal_greatest_common_divisor = Greatest_Common_Divisor(normal_vector_x, normal_vector_y);
//        normal_vector_x = normal_vector_x/normal_greatest_common_divisor;
//        normal_vector_y = normal_vector_y/normal_greatest_common_divisor;
//        int dot_product = DotProduct((getWidth()/2 - m_current_mouse_x), getHeight()/2 - m_current_mouse_y, normal_vector_x, normal_vector_y);
//        System.out.println("dot_product == " + dot_product);
//        int reflect_point_x = (getWidth()/2 - m_current_mouse_x) - 2*dot_product*normal_vector_x;
//        int reflect_point_y = (getHeight()/2 - m_current_mouse_y) - 2*dot_product*normal_vector_y;
//        int reflect_greatest_common_divisor = Greatest_Common_Divisor(reflect_point_x, reflect_point_y);
//        reflect_point_x = reflect_point_x/reflect_greatest_common_divisor;
//        reflect_point_y = reflect_point_y/reflect_greatest_common_divisor;
//        g.setColor(Color.CYAN);
//        g.drawLine(getWidth()/2, getHeight()/2, getWidth()/2 + normal_vector_x, getHeight()/2 + normal_vector_y);
        
//        g.setColor(Color.WHITE);
//        g.drawLine(getWidth()/2, getHeight()/2, getWidth()/2 + reflect_point_x, getHeight()/2 + reflect_point_y);

        //draw mouse position
        g.setColor(Color.BLACK);
        g.drawString("Mouse: " + m_current_mouse_x + "; " + m_current_mouse_y, 5, getHeight() - 10);

         g2d = (Graphics2D) g;//use for rotate any image or shape

        //draw rotate rectangle and triangle
        g.setColor(Color.RED);
        g.drawArc(930, 0, 140, 140, 0, 360);
        g.setColor(Color.GREEN);
        at = g2d.getTransform();
        g2d.translate(1000, 70);
        g2d.rotate(missileangle3);
        g2d.fill(rotate_rect);
        g.setColor(Color.BLUE);
        g2d.fill(rotate_triangle);
        g2d.setTransform(at);
        
         //for eyes
        g.setColor(Color.WHITE);
        g.fillOval(eyesposx - 50, eyesposy - 60, 100, 120);
        g.fillOval(eyesposx - 50 + 100, eyesposy - 60, 100, 120);
        g.setColor(Color.BLACK);
        g.fillOval(eyesirisx1 - 25, eyesirisy1 - 35, 50, 70);
        g.fillOval(eyesirisx2 - 25 + 100, eyesirisy2 - 35, 50, 70);


        //for target
        g.setColor(Color.BLACK);
        g.fillOval(targetx - 20, targety - 20, 40, 40);
        g.setColor(Color.WHITE);
        g.fillOval(targetx - 15, targety - 15, 30, 30);
        g.setColor(Color.BLACK);
        g.fillOval(targetx - 10, targety - 10, 20, 20);
        g.setColor(Color.WHITE);
        g.fillOval(targetx - 5, targety - 5, 10, 10);
        g.setColor(Color.RED);
        g.fillOval(targetx - 2, targety - 2, 4, 4);


        //for taichi enemy
        g.setColor(Color.BLACK);
        g.fillArc(lx - 20, ly - 20, 40, 40, 180 - (int)Math.toDegrees(angle1), 180);
        g.setColor(Color.WHITE);
        g.fillArc(lx - 20, ly - 20, 40, 40, 360 - (int)Math.toDegrees(angle1), 180);
        g.setColor(Color.BLACK);
        g.fillArc(x1 - 10, y1 - 10, 20, 20, 0, 360);
        g.setColor(Color.WHITE);
        g.fillArc(x3 - 10, y3 - 10, 20, 20,  0, 360);
        g.setColor(Color.WHITE);
        g.fillOval(x2 - 2, y2 - 2, 4, 4);
        g.setColor(Color.BLACK);
        g.fillOval(x4 - 2, y4 - 2, 4, 4);

        

        
        g.setColor(Color.BLACK);

        
////        g.fillRect(targetx - 2, targety - 2, 4, 4);


//        g.fillOval(m_taichi_heard_x - 2, m_taichi_heard_y - 2, 4, 4);
        
//        if(come)
//            g.fillOval(hidetagetx - 2, hidetagety - 2, 4, 4);
        if(state > 0)
            g.drawArc(targetx - 20, targety - 40, 40, 40, 360 - (int) Math.toDegrees(angle10), (int) Math.toDegrees(angle10)- 90);
        if(state > 1){
            g.drawArc(targetx - 20, targety - 80, 40, 40, 270, (int) Math.toDegrees(angle11) - 90);
        }        
        if(state > 2){
            g.setColor(blackcolor);
            g.fillArc(targetx - 40, targety - 80, 80, 80, 270, 180);
            g.setColor(whitecolor);
            g.fillArc(targetx - 40, targety - 80, 80, 80, 90, 180);
            g.fillArc(targetx - 20, targety - 80, 40, 40, 270, 180);
            g.setColor(blackcolor);
            g.fillArc(targetx - 20, targety - 40, 40, 40, 90, 180);
//            g.fillOval(targetx - eyewidth/2, targety - 40 - eyewidth/2, eyewidth, eyewidth);
        }
        if(state > 3){
//            g.setColor(Color.BLACK);

            g.setColor(smallcircleblack);
            g.fillOval(x10 - eyewidth/2, y10 - eyewidth/2, eyewidth, eyewidth);
//            g.setColor(Color.WHITE);

            g.setColor(smallcirclewhite);
            g.fillOval(x11 - eyewidth/2, y11 - eyewidth/2, eyewidth, eyewidth);
        }
//        g.drawLine(bulletx, bullety, targetx, targety);
//        g.setColor(Color.YELLOW);
//        g.fillOval(bulletx-2, bullety-2, 4, 4);
//        g.setColor(Color.RED);
//        g.fillOval(bulletxx, bulletyy, 4, 4);
//        g.drawString("m_taichi_heard_x = "+m_taichi_heard_x, targetx, targety);
//        g.drawString("m_taichi_heard_y = "+m_taichi_heard_y, targetx, targety+ 10);
//        g.drawString("targetx = "+targetx, targetx, targety + 20);
//        g.drawString("targety = "+targety, targetx, targety + 30);
//        g.drawString("hidetagetx = "+hidetagetx, targetx, targety + 40);
//        g.drawString("hidetagety = "+hidetagety, targetx, targety + 50);
//        g.drawOval(targetx - 40, targety - 80, 80, 80);
//        g.setColor(Color.BLUE);
//        g.fillOval(m_taichi_heard_x + (m_taichi_heard_x - lx[1])*20 - 2, recaculatehidetagety(m_taichi_heard_x + (m_taichi_heard_x - lx[1])*20) - 2, 4, 4);

//        System.out.println((m_taichi_heard_x - lx[1])*20);
//        Ellipse2D oval = new Ellipse2D.Double(targetx - 40, targety - 80, 80, 80);
//        g.setClip(oval);        
//        g.drawArc(targetx, targety - 60, 20, 20, (int)angle10, (int)(270 - angle10));
//        g.setColor(Color.WHITE);
//        g.drawLine(hidetagetx, hidetagety, targetx, targety);
//        g.setColor(Color.YELLOW);
//        g.drawLine(m_taichi_heard_x, m_taichi_heard_y, hidetagetx, hidetagety);

//        g.setColor(Color.BLACK);
//        g.drawOval(targetx - 40, targety - 40, 80, 80);
        
        
//        Ellipse2D oval = new Ellipse2D.Double(targetx - 40, targety - 40, 80, 80);
//        g.setClip(oval);
//        g.setColor(Color.WHITE);
//        g.fillRect(targetx - 40, targety - 40, 40, 80);
//        g.setColor(Color.BLACK);
//        g.fillRect(targetx, targety - 40, 40, 80);
//        g.setColor(Color.WHITE);
//        g.fillArc(targetx - 20, targety - 40, 40, 40, 270, 180);
//        g.setColor(Color.BLACK);
//        g.fillArc(targetx - 20, targety, 40, 40, 90, 180);
//
//        g.setColor(Color.WHITE);
//        g.fillOval(targetx - 5, targety + 15, 10, 10);
//        g.setColor(Color.BLACK);
//        g.fillOval(targetx - 5, targety - 25, 10, 10);


       


           //draw wall
//        g.setColor(Color.BLACK);
//        g.fillRect(350, 280, 40, 300);


        //draw mc trail
        g.setColor(Color.BLACK);
        for(int i = 0; i < S_MC_TRAIL_POINT_COUNT - 1; i ++){
            g.drawLine(m_mc_trail_point_x[i], m_mc_trail_point_y[i], m_mc_trail_point_x[i+1], m_mc_trail_point_y[i+1]);
        }

        //draw bullet
        try{
        for(int i = 0; i < bulletlist.size(); i ++)
            g.fillRect(bulletlist.get(i).getBulletX() - 1, bulletlist.get(i).getBulletY() - 1, 2, 2);
        }catch(Exception e){}

        //draw mc missile
        for(int i = 0; i < m_missiles_arraylist.size(); i ++){
            at = g2d.getTransform();
            g2d.translate(m_missiles_arraylist.get(i).getMissilePosX(), m_missiles_arraylist.get(i).getMissilePosY());
            g2d.rotate(m_missiles_arraylist.get(i).getMissileCurrentAngle());
            g2d.drawImage(im, -im.getWidth(this)/2, -im.getHeight(this)/2, this);
            g2d.setTransform(at);
        }
        g.setColor(Color.BLACK);
        g.drawString("Missile count == " + m_missiles_arraylist.size(), 5, 75);
        
        //draw mc        
        g.setColor(Color.BLUE);
        at = g2d.getTransform();
        g2d.translate(m_mc_pos_x, m_mc_pos_y);
        g2d.rotate(m_mc_current_angle);
        g2d.fill(m_mc_triangle);
        g2d.setTransform(at);
        
        //draw missile near gun 1
        at = g2d.getTransform();
        g2d.translate(m_mc_missile_1_posx, m_mc_missile_1_posy);
        g2d.rotate(missileangle3);
        g2d.drawImage(im, -im.getWidth(this)/2, -im.getHeight(this)/2, this);
        g2d.setTransform(at);

        //draw missile near gun 2
        at = g2d.getTransform();
        g2d.translate(m_mc_missile_2_posx, m_mc_missile_2_posy);
        g2d.rotate(missileangle3);
        g2d.drawImage(im, -im.getWidth(this)/2, -im.getHeight(this)/2, this);
        g2d.setTransform(at);


        //draw gravity ball
        g.setColor(Color.BLACK);
        g.fillOval(80 + gravityballx - 10, 530 - (gravitybally - 10), 20, 20);
        //draw ball position
//        g.drawString("time = " + (double)((System.currentTimeMillis() - starttime)/1000)+(double)((System.currentTimeMillis() - starttime%1000)/1000), 5, 40);
//        g.drawString("ballvelocityix == "+ ballvelocityix, 5, 25);
//        g.drawString("ballvelocityy == " + ballvelocityy, 5, 40);
//        g.drawString("time * 8 = " + (double)(balltime), 5, 55);

        //draw velocity vetor
        g.setColor(Color.GREEN);
        //draw x velocity
        g.drawLine(80 + gravityballx, 500 - (gravitybally - 50), (int)(80 + gravityballx + ballvelocityix), 500 - (gravitybally - 50));

        //draw y velocity
        g.setColor(Color.BLUE);
        g.drawLine(80 + gravityballx, 500 - (gravitybally - 50), 80 + gravityballx, 500 - (int)(gravitybally - 50 + ballvelocityy));
        
        //draw total velocity
        g.setColor(Color.CYAN);
        g.drawLine(80 + gravityballx, 500 - (gravitybally - 50), (int)(80 + gravityballx + ballvelocityix),500 - (int)(gravitybally - 50 + ballvelocityy));

        //draw gunny
        g.setColor(Color.BLACK);
        //draw static line
        g.drawLine(20, 550, 45, 550);
        //draw Rectangle to store power
        g.drawRect(20, 555, 100, 10);
        g.drawString("Gun Angle = " + gunnyangle, 5, 15);
        g.drawString("Gun Power = " + (int)gunnypower, 5, 30);
        g.drawString("Bullet Pos: " + gunnybulletx + ", " + gunnybullety, 5, 45);
        g.drawString("Bullet Velocity X, Y: " + gunnyvelocityix + ", " + gunnyvelocityy, 5, 60);
        
        //draw gunny gun
        g.drawLine(20, 550, gunnyposx, gunnyposy);
        //draw gunnyangle
        g.drawArc(00, 530, 40, 40, 0, gunnyangle);
        //draw gunnypower
        g.fillRect(20, 555, (int)gunnypower, 10);
        //draw gunny bullet
//        g.translate(gunnyposx, gunnyposy);
        g.setColor(Color.RED);
//        g.fillOval(gunnyposx + gunnybulletx - 5, gunnyposy - gunnybullety - 5, 10, 10);


        if((BULLET_TYPE == BULLET_TYPE_GUNNY)|| (BULLET_TYPE == BULLET_TYPE_RANDOM)){
        //draw physic bullet array
            g.setColor(Color.BLUE);
            if(physicobjectarray != null)
            for(int i = 0; i < physicobjectarray.length; i ++){
                if(physicobjectarray[i] != null){
                    if(BULLET_TYPE == BULLET_TYPE_GUNNY){
                        g.setColor(new Color(0, 0, 255, 255/(i+1)));
//                        g.setColor(new Color(0, 0, 255, 255 - i * 2));
                    }
                    g.fillOval((int)physicobjectarray[i].getPositionX() - 5, (int)physicobjectarray[i].getPositionY() - physicobjectarray[i].getRadius(),  physicobjectarray[i].getRadius()*2, physicobjectarray[i].getRadius()*2);
                }
            }
        }
        g.setColor(Color.GREEN);
//        g.drawString("Physic Object Size == " + physicobjectarray.length, 5, 60);
//        g.drawLine(gunnyposx + gunnybulletx, gunnyposy - gunnybullety, gunnyposx + gunnybulletx + (int)gunnyvelocityix, gunnyposy - gunnybullety);
//        g.setColor(Color.YELLOW);
//        g.drawLine(gunnyposx + gunnybulletx, gunnyposy - gunnybullety, gunnyposx + gunnybulletx, gunnyposy - (int)(gunnybullety + gunnyvelocityy));

//        g.drawString("Gunny y velocity = " +gunnyvelocityy, 5, 60);
//        g.drawString("Gunny y bullet = " +(gunnybullety), 5, 75);
//        g.drawString("Gunny y gun = " +(gunnyposy), 5, 90);

       
        
        if(BULLET_TYPE == BULLET_TYPE_KALSIDDON){
        //daw missile in position of gunny bullet            
            at = g2d.getTransform();
            g2d.translate((gunnyposx + gunnybulletx), (gunnyposy - gunnybullety));
            g2d.rotate(kalsiddon_big_bullet_angle);
            if(gunnybullettime <= timewhenreachtop)
                g2d.drawImage(im, -im.getWidth(this)/2, -im.getHeight(this)/2, this);
            g2d.setTransform(at);
             if(gunnybullettime > timewhenreachtop){
                 g.setColor(Color.RED);
                g.fillRect((gunnyposx + gunnybulletx) - 2, (gunnyposy - gunnybullety) - 2, 4, 4);
//                for(int i = 0; i < kalsiddon_virtual_target.length; i ++){
//                    g.drawLine(kalsiddon_bullet_reached_top_posx, kalsiddon_bullet_reached_top_posy, (int)kalsiddon_virtual_target[i].getX(), (int)kalsiddon_virtual_target[i].getY());
//                    g.fillRect((int)kalsiddon_virtual_target[i].getX() - 3, (int)kalsiddon_virtual_target[i].getY() - 3, 6, 6);
//                }
             }
            //homing missile
    //        g.setColor(Color.RED);
    //        g.drawArc((gunnyposx + gunnybulletx) - 300, (gunnyposy - gunnybullety) - 300, 600, 600,(int) Math.toDegrees(-kalsiddon_big_bullet_angle), 180);
            for(int i = 0; i < max_kalsiddon_child_missile; i ++){
                if(kalsiddon_child_missile[i] != null){
                    at = g2d.getTransform();
                    g2d.translate(kalsiddon_child_missile[i].getMissilePosX(), kalsiddon_child_missile[i].getMissilePosY());
                    g2d.rotate(kalsiddon_child_missile[i].getMissileCurrentAngle());
                    g2d.drawImage(im, -im.getWidth(this)/2, -im.getHeight(this)/2, this);
                    g2d.setTransform(at);
                }
            }            
        }

        //draw mage effect
        if(BULLET_TYPE == BULLET_TYPE_MAGE){
            if(shoted){
                g.setColor(Color.RED);
                g.fillRect((gunnyposx + gunnybulletx) - 2, (gunnyposy - gunnybullety) - 2, 4, 4);
                g.drawLine((gunnyposx + gunnybulletx), (gunnyposy - gunnybullety), (int)(gunnyposx + (gunnybulletx + gunnyvelocityix)), (int)(gunnyposy - (gunnybullety + gunnyvelocityy)));

                g.setColor(Color.CYAN);
                g.fillRect(mage_point1_x - 2, mage_point1_y - 2, 4, 4);
                for(int ii = 0; ii < S_MAGE_TRAIL_LENGTH - 2; ii ++){
                    g.drawLine(mage_delay1_x[ii], mage_delay1_y[ii], mage_delay1_x[ii+1], mage_delay1_y[ii+1]);
                }

                g.setColor(Color.MAGENTA);
                g.fillRect(mage_point2_x - 2, mage_point2_y - 2, 4, 4);
                for(int ii = 0; ii < mage_delay2_x.length - 2; ii ++){
                    g.drawLine(mage_delay2_x[ii], mage_delay2_y[ii], mage_delay2_x[ii+1], mage_delay2_y[ii+1]);
                }

            }
        }
        

//        if(!ismissilecome)
//            g.fillOval(missile.getMissileX() - 10, missile.getMissileY() - 10, 20, 20);
//        g.drawString("missilex == " + missile.getMissileX(), 5, 45);
//        g.drawString("missiley == " + missile.getMissileY(), 5, 60);

         //for smoke missile
        g.drawImage(im, rocketimagex, rocketimagey, this);
        
//        at.rotate(Math.toRadians(0.1));
//        x va y la 2 diem neo co dinh dung de xoay hinh
//        at.rotate(Math.toRadians(0.1), this.getWidth()/2, this.getHeight()/2);
//        at.rotate(Math.toRadians(0.1), this.getWidth()/2, this.getHeight()/2);        
//        at.rotate(Math.toRadians(0.1), this.getWidth()/2, this.getHeight()/2);
//        g.translate(getWidth()/2 - im.getWidth(this)/2, getHeight()/2 - im.getHeight(this)/2);
//         rocketimageangle += Math.toRadians(0.0001);
//         at.rotate(rocketimageangle);
//         g.drawString("rocketimagex == " + rocketimagex, 5, 45);
//         g.drawString("rocketimagey == " + rocketimagey, 5, 60);
       
//        at.setToTranslation((this.getWidth() - im.getWidth(this))/2, (this.getHeight() - im.getHeight(this))/2);
//        at.rotate(rocketimageangle, im.getWidth(this)/2, im.getHeight(this)/2);
//        at.setToTranslation(100, 100);
//        at.rotate(rocketimageangle, 100, 100);

//        if(stransfromdelay == 0){
//            stransfromdelay = 50;
//         at.rotate(1 * Math.PI/180);
//         at.rotate(Math.toRadians(1));
//        g2d = (Graphics2D) g;
//        g2d.setTransform(at);
//        g2d.drawImage(im, rocketimagex, rocketimagey, this);
//        g2d.drawImage(im,getWidth()/2 ,getHeight()/2, this);
//        } else{
//            stransfromdelay --;
//        }

        

        
        //new AffineTranform

//        at.setToTranslation((getWidth() - im.getHeight(this))/2, (getHeight() - im.getHeight(this))/2);
//        at.translate(getWidth()/2,getHeight()/2);
//        rocketimageangle = 0;
//        g.drawString("MissilePosX == " + missileposx, 5, 45);
//        g.drawString("MissilePosY == " + missileposy, 5, 60);
//        at.rotate(rocketimageangle);
//        at.rotate(rocketimageangle);
//        at.translate(getWidth()/2, getHeight()/2);
//        at.rotate(sMath.atan2(getWidth()/2 - targetx, getHeight()/2 - targety));
//        at.rotate(Math.toRadians(0.1));        
        
//        g2sd.setTransform(at);        


         at = g2d.getTransform();
        g2d.translate(missile.getMissilePosX(), missile.getMissilePosY());
//        g2d.translate(getWidth()/2 - im.getHeight(this)/2, 100);
//        g2d.rotate(missileangle1);
//        if(!isgamepause)
            g2d.rotate(missile.getMissileCurrentAngle());
//        g2d.fillRect(-1, -1, 2, 2);
//        g2d.setColor(Color.RED);
//        g2d.fillOval(missileposx - 5, missileposy - 5, 10, 10);
        g2d.drawImage(im, -im.getWidth(this)/2, -im.getHeight(this)/2, this);
        g2d.setTransform(at);


        


        //original
        at = g2d.getTransform();
        g2d.translate(getWidth()/2 - im.getWidth(this)/2, getHeight()/2 - im.getHeight(this)/2);
        g2d.rotate(missileangle2);
        g2d.drawImage(im, -im.getWidth(this)/2, -im.getHeight(this)/2, this);
        g2d.setTransform(at);
        
        
//        g.drawString("missilevelocityx == " + missilevelocityx, 5, 75);
//        g.drawLine(missileposx, missileposy, missileposx + (int)(missilevelocityx*10), missileposy);
//        g.setColor(Color.BLUE);
//        g.drawString("missilevelocityy == " + missilevelocityy, 5, 90);
//        g.drawLine(missileposx, missileposy, missileposx, missileposy - (int)(missilevelocityy*10));
//        g.setColor(Color.GREEN);
//        g.drawLine(missileposx, missileposy, missileposx + (int)(missilevelocityx*10),  missileposy - (int)(missilevelocityy*10));
//        g.setColor(Color.BLACK);

//        g.drawOval(missileposx - dodaidoanthang(missileposx, missileposy, (int)(missileposx + missilevelocityx*10), (int)(missileposy -  missilevelocityy*10)), missileposy - dodaidoanthang(missileposx, missileposy, missileposx + (int)(missilevelocityx*10), missileposy - (int)(missilevelocityy*10)), dodaidoanthang(missileposx, missileposy, (int)(missileposx + missilevelocityx*10), (int)(missileposy - missilevelocityy*10)) * 2, dodaidoanthang(missileposx, missileposy, (int)(missileposx + missilevelocityx*10), (int)(missileposy - missilevelocityy*10)) * 2);
//        g.drawString("missileangle == " + Math.toDegrees(missilecurrentangle), 5, 105);
//        g.drawString("targetangle == " + Math.toDegrees(missiletargetangle), 5, 120);
//        g.drawString("temptargetangle == " + Math.toDegrees(temp_target_angle), 5, 135);
//        g.drawString("max angle left == " + Math.toDegrees(max_left_rotate_angle), 5, 150);
//        g.drawString("max angle right == " + Math.toDegrees(max_right_rotate_angle), 5, 165);


        //draw trail of 5 circle near taichi
        for(int i = 0; i < S_MAX_5_TRAIL_LENGTH - 1; i++){
            g.setColor(Color.RED);
            g.fillOval(x5-5, y5-5, 10, 10);
            g.drawLine(trailtail1posx[i], trailtail1posy[i], trailtail1posx[i+1], trailtail1posy[i+1]);
            g.setColor(Color.GREEN);
            g.fillOval(x6-5, y6-5, 10, 10);
            g.drawLine(trailtail2posx[i], trailtail2posy[i], trailtail2posx[i+1], trailtail2posy[i+1]);
            g.setColor(Color.BLUE);
            g.fillOval(x7-5, y7-5, 10, 10);
            g.drawLine(trailtail3posx[i], trailtail3posy[i], trailtail3posx[i+1], trailtail3posy[i+1]);
            g.setColor(Color.YELLOW);
            g.fillOval(x8-5, y8-5, 10, 10);
            g.drawLine(trailtail4posx[i], trailtail4posy[i], trailtail4posx[i+1], trailtail4posy[i+1]);
            g.setColor(Color.DARK_GRAY);
            g.fillOval(x9-5, y9-5, 10, 10);
            g.drawLine(trailtail5posx[i], trailtail5posy[i], trailtail5posx[i+1], trailtail5posy[i+1]);
        }

        //for debug

//        g.drawLine(missileposx, missileposy, missileposx );
        
//        g2d.setTransform(at);
//        g2d.drawImage(im, 0, 0, this);
        
//        g2d.translate(targetx, targety);
//        g2d.setColor(Color.RED);
//        g2d.drawLine(0, 0, targetx, targety);
//        g.setColor(Color.BLUE);
//        g.drawLine(0, 0, targetx, targety);


//        g.drawImage(im, getWidth()/2 - im.getHeight(this)/2, getHeight()/2 - im.getHeight(this)/2, this);

//        g.setColor(Color.RED);
//        g.drawLine(m_taichi_heard_x, m_taichi_heard_y, 0, 0);
//
//        g.drawRect(m_taichi_heard_x-20, m_taichi_heard_y-20, 40, 40);
//
//        g.setColor(Color.BLACK);
//        if(m_missiles_arraylist.size() > 0)
//        g.drawLine(m_missiles_arraylist.get(0).getMissilePosX(), m_missiles_arraylist.get(0).getMissilePosY(), 0, 0);

        
        
    }
    public void init(){
        addMouseListener(this);
        addMouseMotionListener(this);
    }
    public void resetall(){
        state = 0;
        angle10 = Math.PI/2;
        angle11 = Math.PI/2;
        targetx = random.nextInt(1000);
        targety = random.nextInt(600);
        rwc = 200;
        gwc = 200;
        bwc = 200;
        rbc = 200;
        gbc = 200;
        bbc = 200;
        rmc = 0;
        gmc = 0;
        bmc = 0;
        blackcolor = new Color(rbc, gbc, bbc);
        whitecolor = new Color(rwc, gwc, bwc);        
        createlinefuntion(targetx, targety, m_taichi_heard_x, m_taichi_heard_y);
        
        
        
    }
    public void resetball(){
        //reset ball position
        starttime = System.currentTimeMillis();
        ballvelocityix = (ballvelocity*Math.cos(Math.toRadians(ballangle)));
        ballvelocityiy = (ballvelocity*Math.sin(Math.toRadians(ballangle)));
        balltime = 0;
    }
    public void createlinefuntion(int xa, int ya, int xb, int yb){
        la = (yb - ya);
        lb = (-1)*(xb - xa);
        lc = ((-1)*(yb - ya)*(xa) + (xb - xa)*ya);
    }
    public int recaculatey(int newx){
        int returny = 0;
        if(lb != 0)
          returny = (int)((-1)*la*newx - lc)/lb;
        return returny;
    }
    public int recaculatex(int newy){
        int returnx = 0;
        if(la != 0)
                returnx = (int)((-1)*lb*newy- lc)/la;  
        return returnx;
    }
    public int dodaidoanthang(int xa, int ya, int xb, int yb){
        
        return (int) Math.sqrt(Math.pow((double)(xa - xb), 2) + Math.pow((double)(ya - yb), 2));
    }
    public void createhidelinefuntion(int xa, int ya, int xb, int yb){
        hidelinea = (yb - ya);
        hidelineb = (-1)*(xb - xa);
        hidelinec = ((-1)*(yb - ya)*(xa) + (xb - xa)*ya);
    }
    public void createmissilelinefuntion(int xa, int ya, int xb, int yb){
        missilelineparama = (yb - ya);
        missilelineparamb = (-1)*(xb - xa);
        missilelineparamc = ((-1)*(yb - ya)*(xa) + (xb - xa)*ya);
    }
    public int recalculatemissilex(int missiley){
        int missilex = 0;
        if(missilelineparama != 0)
                missilex = (int)((-1)*missilelineparamb*missiley- missilelineparamc)/missilelineparama;
        return missilex;
    }
    public int recalculatemissiley(int missilex){
        int missiley = 0;
        if(missilelineparamb != 0)
          missiley = (int)((-1)*missilelineparama*missilex - missilelineparamc)/missilelineparamb;
        return missiley;
    }
    
    public int recaculatehidetagety(int newx){
        int returny = 0;
        if(hidelineb != 0)
          returny = (int)((-1)*hidelinea*newx - hidelinec)/hidelineb;
        return returny;
    }
    public int recaculatehidetagetx(int newy){
        int returnx = 0;
        if(hidelinea != 0)
                returnx = (int)((-1)*hidelineb*newy- hidelinec)/hidelinea;  
        return returnx;
    }

    private int DotProduct(int vector1_x, int vector1_y, int vector2_x, int vector2_y){
        return ((vector1_x*vector2_x) + (vector1_y * vector2_y));
    }

    private int Greatest_Common_Divisor(int dividend, int divisor){
        if(dividend > divisor){
            for(int i = divisor; i > 0; i --){
                if(dividend%i==0 && divisor%i ==0){
                    return i;
                }
            }
        }else{
            for(int i = dividend; i > 0; i --){
                if(dividend%i==0 && divisor%i ==0){
                    return i;
                }
            }
        }
        return 1;
    }

    private void Remove_All_MC_Missiles(){        
        while(m_missiles_arraylist.size() > 0){
            m_missiles_arraylist.get(0).finalize();
            m_missiles_arraylist.remove(0);
        }
    }
    private void Remove_MC_Missile(int missile_index){
        m_missiles_arraylist.get(missile_index).finalize();
        m_missiles_arraylist.remove(missile_index);
    }
    private void Reset_MC_Missiles_State(){
        m_mc_current_missile_wave = 0;
        m_is_missile_shooting = false;
        m_mc_missiles_last_shoot_time = 0;
        m_mc_max_missile_per_wave = new int[S_MC_MISSILE_MAX_WAVE];
        m_mc_max_missile_per_wave[0] = 2;//default 2
        m_mc_max_missile_per_wave[1] = 5;//default 5
        m_mc_max_missile_per_wave[2] = 10;//default 10
        m_is_shoot_current_wave = new boolean[S_MC_MISSILE_MAX_WAVE];
        for(int i = 0; i < S_MC_MISSILE_MAX_WAVE; i++){
            m_is_shoot_current_wave[i] = false;
        }
    }

    private void UpdateMCPosition(){
        if(keyuppressed){
            m_mc_pos_y -= MC_MOVE_SPEED;
            if(m_mc_pos_y - MC_RADIUS < 0){
                m_mc_pos_y = MC_RADIUS;
            }
        }
        if(keydownpressed){
            m_mc_pos_y += MC_MOVE_SPEED;
            if(m_mc_pos_y + MC_RADIUS > getHeight()){
                m_mc_pos_y = getHeight() - MC_RADIUS;
            }
        }
        if(keyrightpressed){
            m_mc_pos_x += MC_MOVE_SPEED;
            if(m_mc_pos_x + MC_RADIUS > getWidth()){
                m_mc_pos_x = getWidth() - MC_RADIUS;
            }
        }
        if(keyleftpressed){
            m_mc_pos_x -= MC_MOVE_SPEED;
            if(m_mc_pos_x - MC_RADIUS < 0){
                m_mc_pos_x = MC_RADIUS;
            }
        }
        for(int i = S_MC_TRAIL_POINT_COUNT - 2; i >= 0; i --){
            m_mc_trail_point_x[i+1] = m_mc_trail_point_x[i];
            m_mc_trail_point_y[i+1] = m_mc_trail_point_y[i];
        }
        m_mc_trail_point_x[0] = m_mc_pos_x;
        m_mc_trail_point_y[0] = m_mc_pos_y;
    }

    private void UpdateMCMissiles(){

        for(int i = 0; i < m_missiles_arraylist.size(); i ++){
            m_missiles_arraylist.get(i).relocation(m_taichi_heard_x, m_taichi_heard_y);
        }
        if(m_missiles_arraylist.size() > 0)
            for(int i = m_missiles_arraylist.size() - 1; i >=0 ; i--){
                if(m_missiles_arraylist.get(i).isHitTarget(m_taichi_heard_x, m_taichi_heard_y, 40)){
                    Remove_MC_Missile(i);
                }
            }
     }

    private void Update(){       

    //            bullet a = new bullet(300, 800, targetx, targety);
    //            a.recalculate();
    //            bulletxxa = a.getBulletX();
    //            bulletyy = a.getBulletY();
    //            if(System.currentTimeMillis() - starttime >= 0){
    //                starttime = System.currentTimeMillis();
            //calculate for gravity ball

    //                if(balldelay > 0)
    //                    balldelay --;
    //                else{
    //                    balldelay = 20;
        //homing missile
    //            if(ismissilecome){
    //                missile = new HomingMissile(0, getHeight(), targetx, targety);
    //                ismissilecome = false;
    //            }
    //            else{
    //                missile.relocation(targetx, targety);
    //            }
        missile.relocation(targetx, targety);

        //for new missile
    //            rocketimageangle = Math.atan2(targetx - (getWidth()/2 - im.getWidth(this)/2), targety - (getHeight()/2 - im.getHeight(this)/2));
    //        rocketimageangle = Math.atan2((getWidth()/2 - im.getHeight(this)/2) - targetx, (getHeight()/2 - im.getHeight(this)/2) - targety);
    //            rocketimageangle = Math.toRadians(180) - rocketimageangle;
    //        missilespeed += 1;
    //        if(missilespeed > MISSILE_MAX_SPEED)
    //            missilespeed = MISSILE_MAX_SPEED;
    //            missileangle1 = Math.atan2(targetx - missileposx, targety - missileposy);
    //            missileangle1 = Math.toRadians(180) - missileangle1;
    //            missilevelocityx = missilespeed * Math.sin(missileangle1);
    //            missilevelocityy = missilespeed * Math.cos(missileangle1);




    //            if(shoted){
    //                targetx = gunnyposx + gunnybulletx;
    //                targety = gunnyposy - gunnybullety;
    //            }
    //              missileposx += missilespeed * Math.sin(missileangle1);
    //              missileposy -= missilespeed * Math.cos(missileangle1);

    //              if(Math.abs(targetx - missileposx)>Math.abs(targety - missileposy)){
    //                    if(targetx > missileposx){
    //                        missileposx ++;
    //                    }
    //                    else if(targetx < missileposx)
    //                        missileposx --;
    //                    //The vao phuong trinh duong thang
    //                    missileposy = recalculatemissiley(missileposx);
    //                }
    //                else{
    //                    if(targety > missileposy)
    //                        missileposy ++;
    //                    else if(targety < missileposy)
    //                        missileposy --;
    //                    //The vao phuong trinh duong thang
    //                    missileposx = recalculatemissilex(missileposy);
    //                }
    //                createmissilelinefuntion(targetx, targety, missileposx, missileposy);

                //calculate ball position
                if(balltime > 20){
                    //reset ball position
                    resetball();
                }else{

                    balltime = (System.currentTimeMillis() - starttime)*0.001;
                    balltime *= 8;
                    gravityballx = (int)(ballvelocityix*balltime);
                    gravitybally = (int)(ballvelocityiy*balltime + 0.5*(-9.8)*balltime*balltime);
                    ballvelocityy = ballvelocityiy + (-9.8)*balltime;
                }
    //                }



             //calculate for gunny
             if(!outofscreen){
                 gunnybullettime = (System.currentTimeMillis() - gunnybulletshottime)*0.01;
                 gunnybulletx = (int)(gunnyvelocityix*gunnybullettime);
                 gunnybullety = (int)(gunnyvelocityiy*gunnybullettime + 0.5*(-9.8)*gunnybullettime*gunnybullettime);
                 gunnyvelocityy = gunnyvelocityiy+(-9.8)*gunnybullettime;

                 //for konsiddon shot
                 kalsiddon_big_bullet_angle = Math.atan2((int)gunnyvelocityix, (int)gunnyvelocityy);

                 if(gunnybullettime >= timewhenreachtop){

                     if(create_virtual_taget){
                        kalsiddon_bullet_reached_top_posx = gunnyposx + gunnybulletx;
                        kalsiddon_bullet_reached_top_posy = gunnyposy - gunnybullety;
                        int x;
                        int y;
                        for(int i = 0; i < max_kalsiddon_child_missile; i ++){
                            x = kalsiddon_bullet_reached_top_posx + (int)(200*Math.sin(kalsiddon_big_bullet_angle + Math.toRadians(-60 + i*kalsiddon_angle_pertarget + random.nextInt(kalsiddon_angle_pertarget))));
                            y = kalsiddon_bullet_reached_top_posy + (int)(200*Math.cos(kalsiddon_big_bullet_angle + Math.toRadians(-60 + i*kalsiddon_angle_pertarget + random.nextInt(kalsiddon_angle_pertarget))));
                            kalsiddon_virtual_target[i].x = x;
                            kalsiddon_virtual_target[i].y = y;

                            //create children missile
                            kalsiddon_child_missile[i] = new HomingMissile(gunnyposx + gunnybulletx, gunnyposy - gunnybullety, x, y, 1);
                            kalsiddon_child_missile[i].setMissileCurrentAngle(kalsiddon_big_bullet_angle);
                        }
                        create_virtual_taget = false;
                     }
                 }
             }

             //relocation children missile
             for(int i = 0; i < max_kalsiddon_child_missile; i ++){
                 if(kalsiddon_child_missile[i] != null){
                     if((kalsiddon_child_missile[i].getMissilePosX() > kalsiddon_virtual_target[i].getX() - 10)&&(kalsiddon_child_missile[i].getMissilePosX() < kalsiddon_virtual_target[i].getX() + 10)&&(kalsiddon_child_missile[i].getMissilePosY() > kalsiddon_virtual_target[i].getY() - 10)&&(kalsiddon_child_missile[i].getMissilePosY() < kalsiddon_virtual_target[i].getY() + 10)){
                         hit_virtual_target = true;
                         break;
                     }
                 }
             }
             for(int i = 0; i < max_kalsiddon_child_missile; i ++){
                 if(kalsiddon_child_missile[i] != null)
                     if(!hit_virtual_target){
                        kalsiddon_child_missile[i].relocation(kalsiddon_virtual_target[i].x, kalsiddon_virtual_target[i].y);
                     }else{
                        kalsiddon_child_missile[i].setMissileType(0);
                        if(gunnybullettime >= timewhenreachtop)
                            kalsiddon_child_missile[i].relocation(gunnyposx + gunnybulletx, gunnyposy - gunnybullety);
                     }
            }

            //calculate for gun
            for(int i = 0; i < bulletlist.size(); i ++){
                if(bulletlist.get(i).checkvisible() != true){
                    try {
                        bulletlist.get(i).finalize();
                    } catch (Throwable ex) {
                        Logger.getLogger(BulletPanel.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    bulletlist.remove(i);
                }
            }
            if(m_is_can_fire){
                //control MC
                //for 2 missile near auto gun
                m_mc_current_angle = Math.atan2(m_current_mouse_x - m_mc_pos_x, m_current_mouse_y - m_mc_pos_y);
                m_mc_current_angle = Math.toRadians(180) - m_mc_current_angle;
                m_mc_missile_1_posx = (int)(m_mc_pos_x + S_MC_EQUIPPED_MISSILE_DISTANCE * Math.sin(Math.toRadians(270) - m_mc_current_angle));
                m_mc_missile_1_posy = (int)(m_mc_pos_y + S_MC_EQUIPPED_MISSILE_DISTANCE * Math.cos(Math.toRadians(270) - m_mc_current_angle));
                m_mc_missile_2_posx = (int)(m_mc_pos_x + S_MC_EQUIPPED_MISSILE_DISTANCE * Math.sin(Math.toRadians(90) - m_mc_current_angle));
                m_mc_missile_2_posy = (int)(m_mc_pos_y + S_MC_EQUIPPED_MISSILE_DISTANCE * Math.cos(Math.toRadians(90) - m_mc_current_angle));

                //mc gun shoot
                if(m_is_mc_gun_shooting){                    
                    if(m_mc_delay_beetween_2_bullet > 0)
                        m_mc_delay_beetween_2_bullet --;
                    else{                        
                         bulletlist.add(new Bullet(m_mc_pos_x, m_mc_pos_y, m_current_mouse_x, m_current_mouse_y));
                         bulletlist.get(bulletlist.size() - 1).setSpeed(S_MC_BULLETS_SPEED);
                        m_mc_delay_beetween_2_bullet = 1;
                    }
                }

                //mc missile shoot
                if(m_is_missile_shooting){
                    if(m_mc_current_missile_wave != S_MC_MISSILE_MAX_WAVE){
                        if(!m_is_shoot_current_wave[m_mc_current_missile_wave]){
                            m_is_shoot_current_wave[m_mc_current_missile_wave] = true;
                            m_mc_missiles_last_shoot_time = System.currentTimeMillis();
                            int current_missile_x, current_missile_y;
                            double current_missile_angle = 0;
                            for(int i = 0; i < m_mc_max_missile_per_wave[m_mc_current_missile_wave]; i ++){
                                current_missile_angle += (2*Math.PI)/m_mc_max_missile_per_wave[m_mc_current_missile_wave];
                                current_missile_x = (int)(m_mc_pos_x + S_MC_SHOOT_MISSILE_DISTANCE * Math.sin(current_missile_angle));
                                current_missile_y = (int)(m_mc_pos_y + 25 * Math.cos(current_missile_angle));
                                m_missiles_arraylist.add(new HomingMissile(current_missile_x, current_missile_y, m_taichi_heard_x, m_taichi_heard_y, 0));
                            }
                            current_missile_angle = 0;
                            for(int i = m_missiles_arraylist.size()-1 ; i >= m_missiles_arraylist.size() - m_mc_max_missile_per_wave[m_mc_current_missile_wave]; i--){
                                current_missile_angle += (2*Math.PI)/m_mc_max_missile_per_wave[m_mc_current_missile_wave];
                                m_missiles_arraylist.get(i).setMissileSpeed(5);
                                m_missiles_arraylist.get(i).setMissileCurrentAngle(current_missile_angle - Math.PI);
                            }
                        }
                        if(System.currentTimeMillis() - m_mc_missiles_last_shoot_time > S_MC_MISSILE_WAVE_DELAY_TIME){
                            m_mc_current_missile_wave += 1;
                        }
                    }else if(System.currentTimeMillis() - m_mc_missiles_last_shoot_time > S_MC_MISSILE_SHOOT_DELAY_TIME){
                            Reset_MC_Missiles_State();
                    }
                }

                //for ready missile at gun root
                missileangle3 = Math.atan2(m_current_mouse_x - m_mc_pos_x, m_current_mouse_y - m_mc_pos_y);
                missileangle3 = Math.toRadians(180) - missileangle3;
                //and gun not root
                missileangle2 = Math.atan2(targetx - (getWidth()/2 - im.getWidth(this)/2), targety - (getHeight()/2 - im.getHeight(this)/2));
                missileangle2 = Math.toRadians(180) - missileangle2;
            }else{
                if(m_mc_delay_beetween_2_bullet > 0)
                    m_mc_delay_beetween_2_bullet --;
                else{
                     bulletlist.add(new Bullet(m_mc_pos_x, m_mc_pos_y, m_taichi_heard_x, m_taichi_heard_y));
                    m_mc_delay_beetween_2_bullet = 3;
                }


                //recalculate gun angle if mouse out of screen
                m_mc_current_angle = Math.atan2(m_taichi_heard_x - m_mc_pos_x, m_taichi_heard_y - m_mc_pos_y);
                m_mc_current_angle = Math.toRadians(180) - m_mc_current_angle;

                //for 2 missile near auto gun
                m_mc_missile_1_posx = (int)(m_mc_pos_x + S_MC_EQUIPPED_MISSILE_DISTANCE * Math.sin(Math.toRadians(270) - m_mc_current_angle));
                m_mc_missile_1_posy = (int)(m_mc_pos_y + S_MC_EQUIPPED_MISSILE_DISTANCE * Math.cos(Math.toRadians(270) - m_mc_current_angle));
                m_mc_missile_2_posx = (int)(m_mc_pos_x + S_MC_EQUIPPED_MISSILE_DISTANCE * Math.sin(Math.toRadians(90) - m_mc_current_angle));
                m_mc_missile_2_posy = (int)(m_mc_pos_y + S_MC_EQUIPPED_MISSILE_DISTANCE * Math.cos(Math.toRadians(90) - m_mc_current_angle));



                //for ready missile at gun root
                missileangle3 = Math.atan2(m_taichi_heard_x - m_mc_pos_x, m_taichi_heard_y - m_mc_pos_y);
                missileangle3 = Math.toRadians(180) - missileangle3;
                //and gun not root
                missileangle2 = Math.atan2(targetx - (getWidth()/2 - im.getWidth(this)/2), targety - (getHeight()/2 - im.getHeight(this)/2));
                missileangle2 = Math.toRadians(180) - missileangle2;
            }
            try{
            for(int i = 0; i < bulletlist.size(); i ++){
                bulletlist.get(i).relocation();
            }
            }
            catch(Exception e){}


            if((m_taichi_heard_x == targetx)&&(m_taichi_heard_y == targety)){
    //                    m_taichi_heard_x = random.nextInt(800);
    //                    m_taichi_heard_y = random.nextInt(600);
    //                    m_taichi_heard_x = 400;
    //                    m_taichi_heard_y = 300;
                targetx = random.nextInt(1000);
                targety = random.nextInt(600);
                createlinefuntion(targetx, targety, m_taichi_heard_x, m_taichi_heard_y);

    //                    if(state == 0){
    //                        targetx = random.nextInt(400);// Tao ra toa do x cua muc tieu co the nhin thay duoc moi
    //                        targety = random.nextInt(300);// Tao ra toa do y cua muc tieu co the nhin thay duoc moi
    //                        createlinefuntion(m_taichi_heard_x, m_taichi_heard_y, hidetagetx, hidetagety);
    //                        createlinefuntion(targetx, targety, m_taichi_heard_x, m_taichi_heard_y);
    //                        if(m_taichi_heard_x > lx[0])
    //                            hidetagetx = m_taichi_heard_x + 20;
    //                        else
    //                            hidetagetx = m_taichi_heard_x - 20;
    //                        hidetagetx = m_taichi_heard_x + (m_taichi_heard_x - lx[1])*20;
    //                        hidetagety = recaculatey(hidetagetx);
    //                        createhidelinefuntion(hidetagetx, hidetagety, targetx, targety);
    //                        createlinefuntion(targetx, targety, m_taichi_heard_x, m_taichi_heard_y);
    //                    }

            }
            else{
                if(state == 0){
    //                        if(Math.abs(targetx - hidetagetx)>Math.abs(targety - hidetagety)){
    //                            if(targetx > hidetagetx){
    //                                hidetagetx ++;
    //                            }
    //                            else if(targetx < hidetagetx)
    //                                hidetagetx --;
    //                            //The vao phuong trinh duong thang
    //                            hidetagety = recaculatehidetagety(hidetagetx);
    //                        }
    //                        else{
    //                            if(targety > hidetagety)
    //                                hidetagety ++;
    //                            else if(targety < hidetagety)
    //                                hidetagety --;
    //                            //The vao phuong trinh duong thang
    //                            hidetagetx = recaculatehidetagetx(hidetagety);
    //                        }
                    if(Math.abs(targetx - m_taichi_heard_x)>Math.abs(targety - m_taichi_heard_y)){
                        if(targetx > m_taichi_heard_x){
                            m_taichi_heard_x += 1;
                        }
                        else if(targetx < m_taichi_heard_x)
                            m_taichi_heard_x -= 1;
                        //The vao phuong trinh duong thang
                        m_taichi_heard_y = recaculatey(m_taichi_heard_x);
                    }
                    else{
                        if(targety > m_taichi_heard_y)
                            m_taichi_heard_y += 1;
                        else if(targety < m_taichi_heard_y)
                            m_taichi_heard_y -= 1;
                        //The vao phuong trinh duong thang
                        m_taichi_heard_x = recaculatex(m_taichi_heard_y);
                    }
    //                        createlinefuntion(targetx, targety, m_taichi_heard_x, m_taichi_heard_y);
    //                        if(dodaidoanthang(hidetagetx, hidetagety, targetx, targety) <= 40){
    //                        if((m_taichi_heard_x == targetx)&&(m_taichi_heard_y==targety)&&(m_taichi_heard_y == hidetagetx)){
    //                            come = true;
    //                            state = 1;
    //                        }
                    if((m_taichi_heard_x == targetx)&&(m_taichi_heard_y == targety)){
    //                            come = true;
    //                            state = 1;
                    }
                    else
                        come = false;
                }else if(state == 1){
                    angle10 += 0.1;
                    hidetagetx = (int)(targetx + d3 * Math.cos(angle10));
                    hidetagety = (int)(targety - 20 + d3 * Math.sin(angle10));
                    if(Math.toDegrees(angle10) >= 270){
                        state = 2;
                    }
                }else if(state == 2){
                    if(Math.toDegrees(angle11) < 270)
                        angle11 += 0.1;
                    hidetagetx = (int)(targetx - d3 * Math.cos(angle11));
                    hidetagety = (int)(targety - 60 + d3 * Math.sin(angle11));
                    if(Math.toDegrees(angle11) >= 270){
                        state = 3;
    //                            resetall();
                    }
                }else if(state == 3){
                    if(rwc < 255){
                        rwc++;
                        gwc++;
                        bwc++;
                    }
                    whitecolor = new Color(rwc, gwc, bwc);
                    if(rbc > 0){
                        rbc -= 4;
                        gbc -= 4;
                        bbc -= 4;
                    }
                    blackcolor = new Color(rbc, gbc, bbc);
                    if((rwc == 254)&&(rbc == 0))
                        state = 4;
                }else if(state == 4){
    //                        if(eyewidth > 10)
    //                            eyewidth --;
    //                        angle12 = angle12 + 0.1;
    //                        x10 = (int)(targetx  + 20*Math.cos(angle12));
    //                        y10 = (int)(targety  - 40 + 20*Math.sin(angle12));
    //                        angle13 = angle13 + 0.1;
    //                        x11 = (int)(targetx  + 20* Math.cos(angle13));
    //                        y11 = (int)(targety - 40 + 20*Math.sin(angle13));
    //                        if(Math.toDegrees(angle12) >= 270){
    //                            state = 5;
    //                        }


                    if(rmc < 246){
                        rmc += 9;
                        gmc += 9;
                        bmc += 9;
                    }
                    smallcircleblack = new Color(rmc,gmc,bmc);
                    smallcirclewhite = new Color(255 - rmc, 255 - gmc, 255 - bmc);
                    if(eyewidth > 10)
                        eyewidth --;
                    x10 = targetx;
                    y10 = targety  - 20;
                    x11 = targetx;
                    y11 = targety - 60;

                }

    //                    if(Math.abs(targetx - m_taichi_heard_x)>Math.abs(targety - m_taichi_heard_y)){
    //                        if(targetx > m_taichi_heard_x){
    //                            m_taichi_heard_x ++;
    //                        }
    //                        else if(targetx < m_taichi_heard_x)
    //                            m_taichi_heard_x --;
    //                        //The vao phuong trinh duong thang
    //                        m_taichi_heard_y = recaculatey(m_taichi_heard_x);
    //                    }
    //                    else{
    //                        if(targety > m_taichi_heard_y)
    //                            m_taichi_heard_y ++;
    //                        else if(targety < m_taichi_heard_y)
    //                            m_taichi_heard_y --;
    //                        //The vao phuong trinh duong thang
    //                        m_taichi_heard_x = recaculatex(m_taichi_heard_y);
    //                    }
            }
            lx = m_taichi_heard_x;
            ly = m_taichi_heard_y;
    //                lx[0] = missileposx;
    //                ly[0] = missileposy;
         if(circlesdelay > 0){
                 circlesdelay --;
         }else{
            circlesdelay = 1;

            //calculate for rotate taichi
            angle1 = angle1 - 0.09;
            x1 = (int)(lx + d1 * Math.cos(angle1));
            y1 = (int)(ly+ d1 * Math.sin(angle1));
            angle2 = angle2 - 0.09;
            x2 = (int)(lx + d1 * Math.cos(angle2));
            y2 = (int)(ly + d1 * Math.sin(angle2));
            angle3 = angle3 - 0.09;
            x3 = (int)(lx + d1 * Math.cos(angle3));
            y3 = (int)(ly + d1 * Math.sin(angle3));
            angle4 = angle4 - 0.09;
            x4 = (int)(lx + d1 * Math.cos(angle4));
            y4 = (int)(ly + d1 * Math.sin(angle4));

            //calculate for rorate trail
            angle5 = angle5 - 0.02;
            x5 = (int)(m_taichi_heard_x - d2 * Math.cos(angle5));
            y5 = (int)(m_taichi_heard_y + d2 * Math.sin(angle5));
            angle6 = angle6 - 0.02;
            x6 = (int)(m_taichi_heard_x - d2 * Math.cos(angle6));
            y6 = (int)(m_taichi_heard_y + d2 * Math.sin(angle6));
            angle7 = angle7 - 0.02;
            x7 = (int)(m_taichi_heard_x - d2 * Math.cos(angle7));
            y7 = (int)(m_taichi_heard_y + d2 * Math.sin(angle7));
            angle8 = angle8 - 0.02;
            x8 = (int)(m_taichi_heard_x - d2 * Math.cos(angle8));
            y8 = (int)(m_taichi_heard_y + d2 * Math.sin(angle8));
            angle9 = angle9 - 0.02;
            x9 = (int)(m_taichi_heard_x - d2 * Math.cos(angle9));
            y9 = (int)(m_taichi_heard_y + d2 * Math.sin(angle9));

            //for trail
            if(traildelayupdatetime > 0){
                traildelayupdatetime --;
            }else{
                traildelayupdatetime = 0;
                for(int i = S_MAX_5_TRAIL_LENGTH - 2; i >= 0; i --){
                    trailtail1posx[i+1] = trailtail1posx[i];
                    trailtail1posy[i+1] = trailtail1posy[i];
                    trailtail2posx[i+1] = trailtail2posx[i];
                    trailtail2posy[i+1] = trailtail2posy[i];
                    trailtail3posx[i+1] = trailtail3posx[i];
                    trailtail3posy[i+1] = trailtail3posy[i];
                    trailtail4posx[i+1] = trailtail4posx[i];
                    trailtail4posy[i+1] = trailtail4posy[i];
                    trailtail5posx[i+1] = trailtail5posx[i];
                    trailtail5posy[i+1] = trailtail5posy[i];
                }
             }
            trailtail1posx[0] = (short)x5;
            trailtail1posy[0] = (short)y5;
            trailtail2posx[0] = (short)x6;
            trailtail2posy[0] = (short)y6;
            trailtail3posx[0] = (short)x7;
            trailtail3posy[0] = (short)y7;
            trailtail4posx[0] = (short)x8;
            trailtail4posy[0] = (short)y8;
            trailtail5posx[0] = (short)x9;
            trailtail5posy[0] = (short)y9;
        }
    //                createlinefuntion(targetx, targety, bulletx, bullety);
    //                if(Math.abs(bulletx - targetx)>Math.abs(bullety - targety)){
    //                    if(bulletx > targetx){
    //                        bulletx -=2;
    //                    }
    //                    else if(bulletx < targetx)
    //                        bulletx +=2;
    //                    //The vao phuong trinh duong thang
    //                    bullety = recaculatey(bulletx);
    //                }
    //                else{
    //                    if(bullety > targety)
    //                        bullety -=2;
    //                    else if(bullety < targety)
    //                        bullety +=2;
    //                    //The vao phuong trinh duong thang
    //                    bulletx = recaculatex(bullety);
    //                }
    //                if((bulletx == targetx)&&(bullety == targety)){
    //                    bulletx = 400;
    //                    bullety = 600;
    //                }


            //for eyes
            double eyesirisdistance1;
            double eyesirisdistance2;
            int target_x;
            int target_y;
            if(outofscreen){
                target_x = m_taichi_heard_x;
                target_y = m_taichi_heard_y;
            }else{
                target_x = gunnyposx + gunnybulletx;
                target_y = gunnyposy - gunnybullety;
            }
            eyesangletorotate1 = Math.atan2(eyesposx - target_x, eyesposy - target_y);
            eyesangletorotate2 = Math.atan2(eyesposx + 100 - target_x, eyesposy - target_y);
            eyesirisdistance1 = Math.sqrt((target_x - eyesposx)*(target_x - eyesposx)+(target_y - eyesposy)*(target_y - eyesposy));
            eyesirisdistance2 = Math.sqrt((target_x - (eyesposx + 100))*(target_x -(eyesposx + 100))+(target_y - eyesposy)*(target_y - eyesposy));

            if((int)Math.abs(eyesirisdistance1) > maxeyesirisdistance){
            eyesirisx1 = (int)(eyesposx - maxeyesirisdistance * Math.sin(eyesangletorotate1));//toa do x theo cos moi dung
            eyesirisy1 = (int)(eyesposy - maxeyesirisdistance * Math.cos(eyesangletorotate1));//toa do y theo sin moi dung
            }else{
                  eyesirisx1 = target_x;
                  eyesirisy1 = target_y;
            }
            if((int)Math.abs(eyesirisdistance2) > maxeyesirisdistance){
                eyesirisx2 = (int)(eyesposx - maxeyesirisdistance * Math.sin(eyesangletorotate2));//toa do x theo cos moi dung
                eyesirisy2 = (int)(eyesposy - maxeyesirisdistance * Math.cos(eyesangletorotate2));//toa do y theo sin moi dung
            }else{
                  eyesirisx2 = target_x - 100;
                  eyesirisy2 = target_y;
            }

            //create physicobject
            if(currentobject < maxphysicobject){
                if(physicobjectarray != null && physicobjectarray[0] != null){
                    if((((System.currentTimeMillis() - physicobjectarray[0].getReleaseTime()) / timebetweentwoobject) > currentobject)){
                        switch(BULLET_TYPE){
                            case BULLET_TYPE_GUNNY://type gunny
                                physicobjectarray[currentobject] = new PhysicObject(gunnyposx, gunnyposy, gunnypower, gunnyangle);
                                break;
                            case BULLET_TYPE_RANDOM://type random
                                physicobjectarray[currentobject] = new PhysicObject(gunnyposx, gunnyposy, gunnypower, gunnyangle + random.nextInt(3));
                                break;
                            case BULLET_TYPE_KALSIDDON:
                                break;
                        }
                        currentobject ++;
                    }
                }
            }
            

            //update all bullet type
            switch(BULLET_TYPE){
                case BULLET_TYPE_GUNNY:
                case BULLET_TYPE_RANDOM:
                    if(physicobjectarray != null){
                        for(int i = 0; i < physicobjectarray.length; i ++)
                            if(physicobjectarray[i] != null){
                                physicobjectarray[i].Update();
                                if(physicobjectarray[maxphysicobject - 1] != null)
                                if(physicobjectarray[maxphysicobject - 1].getPositionY() > getHeight())
                                    outofscreen = true;
                            }
                    }
                    break;
                case BULLET_TYPE_KALSIDDON:
                    for(int i = 0; i < max_kalsiddon_child_missile; i ++){
                        if(kalsiddon_child_missile[i] != null){
                            if(kalsiddon_child_missile[i].getMissilePosY() < getHeight()){
                                continue;
                            }
                            outofscreen = true;
                        }
                    }
                    break;
                case BULLET_TYPE_MAGE:
                    //to do: correct calculate here
                    if(shoted){
                        mage_virtual_taget_angle = Math.atan2((gunnyposx + (gunnybulletx + gunnyvelocityix)) - (gunnyposx + gunnybulletx), (gunnyposy - (gunnybullety + gunnyvelocityy)) - (gunnyposy - gunnybullety));
    //                            mage_angle1 = gunnyangle + Math.toRadians(90);
    //                            mage_virtual_taget_angle
                        m_mage_current_angle += Math.toRadians(S_MAGE_ADDITION_ANGLE);
    //                            mage_point1_x = (int)((gunnyposx + gunnybulletx) + 30 * Math.cos(mage_virtual_taget_angle));
    //                            mage_point1_x = (int)((gunnyposx + gunnybulletx) - 30 * Math.sin(mage_angle1));

    //                            mage_point1_x = (int)((gunnyposx + gunnybulletx) + 30 * Math.cos(Math.toRadians(90)));
    //                            mage_point1_y = (int)((gunnyposy - gunnybullety) + 30 * Math.sin(Math.toRadians(90) - mage_angle1));
    //                            mage_point1_y = (int)((gunnyposy - gunnybullety) * Math.cos(0));
                        mage_point1_x = (int)((gunnyposx + gunnybulletx) + S_MAGE_POINT_MAX_DISTANCE*(Math.sin(m_mage_current_angle)) * Math.sin(mage_virtual_taget_angle + Math.PI/2));
                        mage_point1_y = (int)((gunnyposy - gunnybullety) + S_MAGE_POINT_MAX_DISTANCE*(Math.sin(m_mage_current_angle)) * Math.cos(mage_virtual_taget_angle + Math.PI/2));
    //                            mage_point1_y = (int)((gunnyposx - gunnybulletx) - 30 * Math.cos(mage_angle1));
    //                            mage_point1_y = 200;

                        //code follow y direction
    //                            mage_point1_x = (int)((gunnyposx + gunnybulletx));
    //                            mage_point1_y = (int)((gunnyposy - gunnybullety) + 30 * Math.cos(mage_angle1));

                        mage_point2_x = (int)((gunnyposx + gunnybulletx) + S_MAGE_POINT_MAX_DISTANCE*(Math.sin(m_mage_current_angle)) * Math.sin(mage_virtual_taget_angle - Math.PI/2));
                        mage_point2_y = (int)((gunnyposy - gunnybullety) + S_MAGE_POINT_MAX_DISTANCE*(Math.sin(m_mage_current_angle)) * Math.cos(mage_virtual_taget_angle - Math.PI/2));//point 1 in the right of virtal target


                        for(int ii = S_MAGE_TRAIL_LENGTH - 1; ii > 0; ii --){
                            mage_delay1_x[ii] = mage_delay1_x[ii-1];
                            mage_delay1_y[ii] = mage_delay1_y[ii-1];

                            mage_delay2_x[ii] = mage_delay2_x[ii-1];
                            mage_delay2_y[ii] = mage_delay2_y[ii-1];
                        }
                        mage_delay1_x[0] = mage_point1_x;
                        mage_delay1_y[0] = mage_point1_y;

                        mage_delay2_x[0] = mage_point2_x;
                        mage_delay2_y[0] = mage_point2_y;
                    }
                    if(mage_delay1_y[S_MAGE_TRAIL_LENGTH - 1] > getHeight()){
                        outofscreen = true;
                    }
                    break;
            }

            //check and destroy
            if(outofscreen){
                shoted = false;
                switch(BULLET_TYPE){
                    case BULLET_TYPE_GUNNY:
                    case BULLET_TYPE_RANDOM:
                        if(physicobjectarray != null)
                        for(int i = 0; i < maxphysicobject; i ++){
                            if(physicobjectarray[i] != null){
                                physicobjectarray[i].Destroy();
                                physicobjectarray[i] = null;
                            }
                        }
                        break;
                    case BULLET_TYPE_KALSIDDON:
                        create_virtual_taget = true;
                        for(int i = 0; i < max_kalsiddon_child_missile; i ++){
                            if(kalsiddon_child_missile[i] != null){
                                if((kalsiddon_child_missile[i].getMissilePosX() > getWidth() + 10) || (kalsiddon_child_missile[i].getMissilePosY() > getHeight() + 10)){
                                    kalsiddon_child_missile[i] = null;
                                }
                            }
                        }
                        break;
                    case BULLET_TYPE_MAGE:
                        mage_point1_x = mage_point2_x = gunnyposx;
                        mage_point1_y = mage_point2_y = gunnyposy;
                         for(int ii = 0; ii < mage_delay1_x.length; ii ++){
                            mage_delay1_x[ii] = gunnyposx;
                            mage_delay1_y[ii] = gunnyposy;

                            mage_delay2_x[ii] = gunnyposx;
                            mage_delay2_y[ii] = gunnyposy;
                        }

                        break;
                }
            }
            UpdateMCPosition();
            UpdateMCMissiles();
            repaint();
    }

    public void mouseDragged(MouseEvent e) {
        m_current_mouse_x = e.getX();
        m_current_mouse_y = e.getY();
    }

    public void mouseMoved(MouseEvent e) {
        m_is_can_fire = true;
        m_current_mouse_x = e.getX();
        m_current_mouse_y = e.getY();
//        targetx = e.getX();
//        targety = e.getY();
//        mousex = targetx;
//        mousey = targety;
//        createlinefuntion(targetx, targety, m_taichi_heard_x, m_taichi_heard_y);
//        hidetagetx = m_taichi_heard_x + (m_taichi_heard_x - lx[59]);
//        hidetagety = recaculatey(hidetagetx);
//        createhidelinefuntion(hidetagetx, hidetagety, targetx, targety);
//        createlinefuntion(targetx, targety, m_taichi_heard_x, m_taichi_heard_y);
//        createlinefuntion(lx[0], ly[0], m_taichi_heard_x, m_taichi_heard_y);
//        lx[0] = e.getX();
//        ly[0] = e.getY();



        //recalculate gun angle
//        m_mc_current_angle = Math.atan2(m_current_mouse_x - m_mc_pos_x, m_current_mouse_y - m_mc_pos_y);
//        gunangledegrees = (int)(m_mc_current_angle * 180/Math.PI);
//        m_mc_gun_head_x = (int)(m_mc_pos_x + 40 * Math.sin(m_mc_current_angle));//toa do x theo cos moi dung
//        m_mc_gun_head_y = (int)(m_mc_pos_y + 40 * Math.cos(m_mc_current_angle));//toa do y theo sin moi dung
//        missileneargun1posx = (int)(m_mc_pos_x + 22 * Math.sin(m_mc_current_angle + Math.toRadians(90)));
//        missileneargun1posy = (int)(m_mc_pos_y + 22 * Math.cos(m_mc_current_angle + Math.toRadians(90)));
//        missileneargun2posx = (int)(m_mc_pos_x + 22 * Math.sin(m_mc_current_angle - Math.toRadians(90)));
//        missileneargun2posy = (int)(m_mc_pos_y + 22 * Math.cos(m_mc_current_angle - Math.toRadians(90)));

        //for eyes
//        if(outofscreen){
//             lookfollowmouse = true;
//        }
       

        

//        rocketimageangle = 0;        
//        missileangle2 = Math.atan2(targetx - (getWidth()/2 - im.getWidth(this)/2), targety - (getHeight()/2 - im.getHeight(this)/2));
//        missileangle3 = Math.atan2(targetx - m_mc_pos_x, targety - m_mc_pos_y);
//        missileangle2 = Math.toRadians(180) - missileangle2;
//        missileangle3 = Math.toRadians(180) - missileangle3;



//        missiletargetangle = Math.atan2(targetx - missileposx, targety - missileposy);
//        missiletargetangle = Math.toRadians(180) - missiletargetangle;
//        if(missilecurrentangle < Math.toRadians(0))
//            missilecurrentangle += Math.toRadians(360);
//        else if(missilecurrentangle > Math.toRadians(360))
//            missilecurrentangle -= Math.toRadians(360);
//        missileangletorotate = missiletargetangle - missilecurrentangle;
//        if(missileangletorotate > Math.toRadians(180)){
//            missileangletorotate = Math.toRadians(360) - missiletargetangle;
//            if(missileangletorotate > MISSILE_MAX_ROTATE_ANGLE){
//                missileangletorotate = -MISSILE_MAX_ROTATE_ANGLE;
//            }else{
//                missileangletorotate *= -1;
//            }
//        }else{
//            if(missileangletorotate > MISSILE_MAX_ROTATE_ANGLE){
//                missileangletorotate = MISSILE_MAX_ROTATE_ANGLE;
//            }
//        }

//            max_left_rotate_angles = -MISSILE_MAX_ROTATE_ANGLE;
            
//            missile.relocation(msousex, targety);

            //missile array
//            for(int i = 0; i < m_missiles_arraylist.size(); i ++){
//                m_missiles_arraylist.get(i).relocation(targetx, targety);
//            }

//            missilecurrentangle += missileangletorotate;
//            if(missilecurrentangle < 0)
//                missilecurrentangle += Math.toRadians(360);
//            if(missilecurrentangle > Math.toRadians(360))
//                missilecurrentangle -= Math.toRadians(360);
//            missilevelocityx = missilespeed * Math.sin(missilecurrentangle);
//            missilevelocityy = missilespeed * Math.cos(missilecurrentangle);

//         missileposx += (int)missilevelocityx;
//         missileposy -= (int)missilevelocityy;
//        createmissilelinefuntion(targetx, targety, missileposx, missileposy);
//        missilevelocityx = missilespeed * Math.sin(missileangle1);
//        missilevelocityy = missilespeed * Math.cos(missileangle1);
        
        
//        missilespeed += 1;
//        if(missilespeed > MISSILE_MAX_SPEED)
//            missilespeed = MISSILE_MAX_SPEED;
//        missileposx += (int)missilespeed*Math.sin(rocketimageangle);
//        missileposy -= (int)missilespeed*Math.cos(rocketimageangle);
//        double angletorotate = targetangle - rocketimageangle;
//        rocketimageangle += angletorotate;
//        oldangle = newangle;
//            rocketimageangle += Math.toRadians(1);
        //for missile
//        missile.relocation(e.getX(), e.getY());
//        missile.update();
        repaint();

        //calculate for rocket
//        rocketimageangle = Math.atan2(e.getX() - rocketimagex, e.getY() - rocketimagey);

//        x8 = (int)(targetx - d2 * Math.cos(angle8));
//                y8 = (int)(targety + d2 * Math.sin(angle8));
//        double targetAngle = Math.atan2(m_mc_gun_head_x - e.getX(), m_mc_gun_head_y - e.getY());
//        double angleToRotate = targetAngle - directionAngle;
//        if(angleToRotate > 3.1415926535897931D)
//            angleToRotate -= 6.2831853071795862D;
//        if(angleToRotate < -3.1415926535897931D)
//            angleToRotate += 6.2831853071795862D;
//        if(Math.abs(angleToRotate) > 0.050000000000000003D)
//            if(angleToRotate < 0.0D)
//                angleToRotate = -0.050000000000000003D;
//            else
//                angleToRotate = 0.050000000000000003D;
//        directionAngle += angleToRotate;
//        m_mc_gun_head_x -= 10*Math.sin(directionAngle);
//        m_mc_gun_head_y -= 10*Math.cos(directionAngle);
    }



    

    public void mouseClicked(MouseEvent e) {
//        targetx = e.getX();
//        targety = e.getY();
//        if(running)
//            running = false;
//        else
//            running = true;
//        isgamepause = !isgamepause;
//        if(e.getButton() == MouseEvent.BUTTON3){
//            isgamepause = !isgamepause;
//            missileposx = 500;
//            missileposy = 730;
//        }
//        resetall();
        

//        resetball();        
    }

    public void mousePressed(MouseEvent e) {
        if(e.getButton() == MouseEvent.BUTTON1){            
            m_is_mc_gun_shooting = true;
            m_current_mouse_x = e.getX();
            m_current_mouse_y = e.getY();
        }else if(e.getButton() == MouseEvent.BUTTON2){
            Remove_All_MC_Missiles();
            Reset_MC_Missiles_State();
        }else if(e.getButton() == MouseEvent.BUTTON3){
            m_is_missile_shooting = true;
            
        }
        
    }

    public void mouseReleased(MouseEvent e) {
        if(e.getButton() == MouseEvent.BUTTON1){
            m_is_mc_gun_shooting = false;
        }else if(e.getButton() == MouseEvent.BUTTON2){
            
        }else if(e.getButton() == MouseEvent.BUTTON3){
//            m_mc_position_to_move_x = e.getX();
//            m_mc_position_to_move_y = e.getY();
        }
    }

    public void mouseEntered(MouseEvent e) {
//        lookfollowmouse = false;
//        lookfollowmouse = true;
//        System.out.println("Entered");
        m_is_can_fire = true;
    }

    public void mouseExited(MouseEvent e) {
//        System.out.println("Exited");
//        lookfollowmouse = false;
        m_is_can_fire = false;
    }
    public void keyPressed(KeyEvent e) {
        if(e.getKeyCode() == KeyEvent.VK_ENTER){
           m_is_game_pause = !m_is_game_pause;
        }
        if(e.getKeyCode() == KeyEvent.VK_SPACE)
            outofscreen = true;
        if(e.getKeyCode() == KeyEvent.VK_UP){
            if(gunnyangle < 90){
                gunnyangle++;
                gunnyposx = (int)(20 + 40* Math.cos(Math.toRadians(gunnyangle)));
                gunnyposy = (int)(550 - 40* Math.sin(Math.toRadians(gunnyangle)));
                ballangle = 90 - gunnyangle;
            }
            
        }
        else if(e.getKeyCode() == KeyEvent.VK_DOWN)
        {
            if(gunnyangle > 0){
                gunnyangle--;
                gunnyposx = (int)(20 + 40* Math.cos(Math.toRadians(gunnyangle)));
                gunnyposy = (int)(550 - 40* Math.sin(Math.toRadians(gunnyangle)));
                ballangle = 90 - gunnyangle;
            }
        }
        else if(e.getKeyCode() == KeyEvent.VK_SPACE)
        {           
            if(shoted){
                gunnypower = 80;
                shoted = false;
            }
            if(!powerdirectiondown){
                gunnypower++;
                if(gunnypower == 100){
                    powerdirectiondown = true;
                }
            }
            else{
                gunnypower --;
                if(gunnypower == 0){
                    powerdirectiondown = false;
                }
            }
        }
        if(e.getKeyCode() == KeyEvent.VK_A){
           keyleftpressed = true;
        }

        if(e.getKeyCode() == KeyEvent.VK_D){
            keyrightpressed = true;
        }

        if(e.getKeyCode() == KeyEvent.VK_W){
           keyuppressed = true;
        }

        if(e.getKeyCode() == KeyEvent.VK_S){
            keydownpressed = true;
       }    
    }

    public void keyTyped(KeyEvent e) {
        
    }

    public void keyReleased(KeyEvent e) {
        if(e.getKeyCode() == KeyEvent.VK_SPACE){
            if(gunnypower < 80)
            gunnypower = 80;
            outofscreen = false;
            shoted = true;
            powerdirectiondown = false;
            hit_virtual_target = false;
            gunnybulletshottime = System.currentTimeMillis();            
            gunnyvelocityix = (gunnypower*Math.cos(Math.toRadians(gunnyangle)));
            gunnyvelocityiy = (gunnypower*Math.sin(Math.toRadians(gunnyangle)));
            gunnyvelocityy = gunnyvelocityiy+(-9.8)*gunnybullettime;     
            timewhenreachtop = -gunnyvelocityiy/-9.8;
            currentobject = 0;
            physicobjectarray = new PhysicObject[maxphysicobject];
            physicobjectarray[currentobject] = new PhysicObject(gunnyposx, gunnyposy, gunnypower, gunnyangle);
            currentobject ++;
            pressed_count ++;
            for(int i = 0; i < max_kalsiddon_child_missile; i ++){
                kalsiddon_child_missile[i] = null;
            }
        }
         if(e.getKeyCode() == KeyEvent.VK_A){
           keyleftpressed = false;
        }

        if(e.getKeyCode() == KeyEvent.VK_D){
            keyrightpressed = false;
        }

        if(e.getKeyCode() == KeyEvent.VK_W){
           keyuppressed = false;
        }

        if(e.getKeyCode() == KeyEvent.VK_S){
            keydownpressed = false;
       }
    }
    
    public void run() {
        while(true){
            try{
                Thread.sleep(5);
            }
            catch(Exception e){}
            if(!m_is_game_pause)
                Update();
        }
    }
}